export interface SpecificLotteryRateItem<T> {
    rate: number;
    data: T;
}

export default class SpecificLotteryRate<T> {
    private readonly list: SpecificLotteryRateItem<T>[] = [];
    private readonly total: number = 0;

    private constructor(list: SpecificLotteryRateItem<T>[]) {
        list = list.filter(item => 0 < item.rate);

        if (0 < list.length) {
            this.list = list.map(item => ({...item,}));
            this.total = list.reduce((res, item) => res + item.rate, 0);
        } else {
            throw new RangeError('the "list" parameter do not have valid item.');
        }
    }

    public getOne(): T {
        const rand = this.total * Math.random();

        let start: number = 0;
        const res = this.list.find(item => start <= rand && rand < (start += item.rate));

        return (res as SpecificLotteryRateItem<T>).data;
    }


    public static getInstance<P>(list: SpecificLotteryRateItem<P>[]) {
        return new SpecificLotteryRate<P>(list);
    }
}
